using NUnit.Framework;
using SpecificationPatternCodeV2.Abstracts;
using SpecificationPatternCodeV2.Base;

namespace SpecificationPatternTestsV2
{
	[TestFixture]
	public class CompositeSpecificationFixture
	{
		[Test]
		public void ensure_that_9_matches_GreaterThan5AndLessThan10ButNot678_specification()
		{
			var spec = new GreaterThanOrEqualTo5AndLessThanOrEqualTo10ButNot678OrCanBe11();
			Assert.False(spec.IsSatisfiedBy(1));
			Assert.False(spec.IsSatisfiedBy(2));
			Assert.False(spec.IsSatisfiedBy(3));
			Assert.False(spec.IsSatisfiedBy(4));
            Assert.True(spec.IsSatisfiedBy(5));
            Assert.False(spec.IsSatisfiedBy(6));
			Assert.False(spec.IsSatisfiedBy(7));
			Assert.False(spec.IsSatisfiedBy(8));
            Assert.True(spec.IsSatisfiedBy(9));
			Assert.True(spec.IsSatisfiedBy(10));
			Assert.True(spec.IsSatisfiedBy(11));
			Assert.False(spec.IsSatisfiedBy(12));
		}
	}

	public class GreaterThanOrEqualTo5AndLessThanOrEqualTo10ButNot678OrCanBe11 : CompositeSpecification<int>
	{
		private static readonly RangeSpecification<int> OuterRange = new RangeSpecification<int>(5, 10);
		private static readonly RangeSpecification<int> InnerRange = new RangeSpecification<int>(6, 8);
		private static readonly EqualsSpecification<int> OrValue = new EqualsSpecification<int>(11);

		public override bool IsSatisfiedBy(int candidate)
		{
			return OuterRange.And(InnerRange.Not()).Or(OrValue).IsSatisfiedBy(candidate);
		}
	}
}